/**
  ******************************************************************************
* @file				oled.c
* @Software			IAR 8.3 or MDK 5.28
* @Target 			CW32F030C8T6
* @author			何月明
* @date				2023-0617
  ******************************************************************************
  */


#include "oled_simiic.h"
#include "oled_font.h"


//OLED的显存
//存放格式如下.
//[0]0 1 2 3 ... 127	
//[1]0 1 2 3 ... 127	
//[2]0 1 2 3 ... 127	
//[3]0 1 2 3 ... 127	
//[4]0 1 2 3 ... 127	
//[5]0 1 2 3 ... 127	
//[6]0 1 2 3 ... 127	
//[7]0 1 2 3 ... 127 	

/*引脚初始化*/
void OLED_SIMIIC_Init(void)
{
	__RCC_GPIOB_CLK_ENABLE();
	
	GPIO_InitTypeDef GPIO_InitStructure;
 	GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
	GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
	GPIO_InitStructure.IT = GPIO_IT_NONE;
	
	GPIO_InitStructure.Pins = OLED_SCL_PIN;
 	GPIO_Init(OLED_SCL_PORT, &GPIO_InitStructure);
	GPIO_InitStructure.Pins = OLED_SDA_PIN;
 	GPIO_Init(OLED_SDA_PORT, &GPIO_InitStructure);
}
		   
/**********************************************
//IIC Start
**********************************************/
void OLED_IIC_Start()
{
	OLED_SCL_HIGH();
	OLED_SDA_HIGH();
	OLED_SDA_LOW();
	OLED_SCL_LOW();
}

/**********************************************
//IIC Stop
**********************************************/
void OLED_IIC_Stop()
{
	OLED_SCL_HIGH() ;
//	OLED_SCL_LOW();
	OLED_SDA_LOW();
	OLED_SDA_HIGH();
}

/**********************************************
//OLED_IIC_WaitAck
**********************************************/
void OLED_IIC_WaitAck()
{

	//GPIOB->CRH &= 0XFFF0FFFF;	//设置PB12为上拉输入模式
	//GPIOB->CRH |= 0x00080000;
//	OLED_SDA = 1;
//	delay_us(1);
	//OLED_SCL = 1;
	//delay_us(50000);
/*	while(1)
	{
		if(!OLED_SDA)				//判断是否接收到OLED 应答信号
		{
			//GPIOB->CRH &= 0XFFF0FFFF;	//设置PB12为通用推免输出模式
			//GPIOB->CRH |= 0x00030000;
			return;
		}
	}
*/
	OLED_SCL_HIGH() ;
	OLED_SCL_LOW();
}
/**********************************************
// IIC Write byte
**********************************************/
void OLED_IIC_WriteByte(uint8_t IIC_Byte)
{
	uint8_t i;
	uint8_t m,da;
	da=IIC_Byte;
	OLED_SCL_LOW();
	for(i=0;i<8;i++)		
	{
		m=da;
		m=m&0x80;
		if(m==0x80)		OLED_SDA_HIGH();
		else 			OLED_SDA_LOW();
		da=da<<1;
		OLED_SCL_HIGH();
		OLED_SCL_LOW();
	}
}
/**********************************************
// IIC Write Command
**********************************************/
void OLED_IIC_WriteCommand(uint8_t IIC_Command)
{
   OLED_IIC_Start();
   OLED_IIC_WriteByte(0x78);            //Slave address,SA0=0 地址位
	OLED_IIC_WaitAck();	
   OLED_IIC_WriteByte(0x00);			//write command
	OLED_IIC_WaitAck();	
   OLED_IIC_WriteByte(IIC_Command); 
	OLED_IIC_WaitAck();	
   OLED_IIC_Stop();
}
/**********************************************
// IIC Write Data
**********************************************/
void OLED_IIC_WriteData(uint8_t IIC_Data)
{
   OLED_IIC_Start();
   OLED_IIC_WriteByte(0x78);			//D/C#=0; R/W#=0  地址位
	OLED_IIC_WaitAck();	
   OLED_IIC_WriteByte(0x40);			//write data
	OLED_IIC_WaitAck();	
   OLED_IIC_WriteByte(IIC_Data);
	OLED_IIC_WaitAck();	
   OLED_IIC_Stop();
}
///**********************************************
//// 	OLED_WR_Byte
//**********************************************/
void OLED_WR_Byte(unsigned dat,unsigned cmd)
{
	 OLED_IIC_Start();
   OLED_IIC_WriteByte(0x78);			//D/C#=0; R/W#=0
	OLED_IIC_WaitAck();	
   OLED_IIC_WriteByte(cmd);			
	OLED_IIC_WaitAck();	
   OLED_IIC_WriteByte(dat);
	OLED_IIC_WaitAck();	
   OLED_IIC_Stop();
}

/********************************************
// OLED_FillPicture
********************************************/
void OLED_FillPicture(uint8_t fill_Data)
{
	uint8_t m,n;
	for(m=0;m<8;m++)
	{
		OLED_WR_Byte(0xb0+m,OLED_CMD);		//page0-page1
		OLED_WR_Byte(0x00,OLED_CMD);		//low column start address
		OLED_WR_Byte(0x10,OLED_CMD);		//high column start address
		for(n=0;n<128;n++)
			{
				OLED_WR_Byte(fill_Data,OLED_DATA);
			}
	}
}

/***********************	坐标设置	***********************/
void OLED_SetPos(uint8_t x, uint8_t y) 
{ 	
  OLED_WR_Byte(0xb0+y,OLED_CMD);
  OLED_WR_Byte(((x&0xf0)>>4)|0x10,OLED_CMD);
  OLED_WR_Byte((x&0x0f),OLED_CMD); 
}  
//清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样!!!	  
void OLED_Clear(void)  
{  
	uint8_t i,n;		    
	for(i=0;i<8;i++)  
	{  
		OLED_WR_Byte (0xb0+i,OLED_CMD);    //设置页地址（0~7）
		OLED_WR_Byte (0x00,OLED_CMD);      //设置显示位置—列低地址
		OLED_WR_Byte (0x10,OLED_CMD);      //设置显示位置—列高地址   
		for(n=0;n<128;n++)OLED_WR_Byte(0,OLED_DATA); 
	} //更新显示
}
//开启OLED显示    
void OLED_DisplayOn(void)
{
	OLED_WR_Byte(0X8D,OLED_CMD);  //SET DCDC命令
	OLED_WR_Byte(0X14,OLED_CMD);  //DCDC ON
	OLED_WR_Byte(0XAF,OLED_CMD);  //DISPLAY ON
}
//关闭OLED显示     
void OLED_DisplayOff(void)
{
	OLED_WR_Byte(0X8D,OLED_CMD);  //SET DCDC命令
	OLED_WR_Byte(0X10,OLED_CMD);  //DCDC OFF
	OLED_WR_Byte(0XAE,OLED_CMD);  //DISPLAY OFF
}		   			 

//
void OLED_On(void)  
{  
	uint8_t i,n;		    
	for(i=0;i<8;i++)  
	{  
		OLED_WR_Byte (0xb0+i,OLED_CMD);    //设置页地址（0~7）
		OLED_WR_Byte (0x00,OLED_CMD);      //设置显示位置—列低地址
		OLED_WR_Byte (0x10,OLED_CMD);      //设置显示位置—列高地址   
		for(n=0;n<128;n++)OLED_WR_Byte(1,OLED_DATA); 
	} //更新显示
}


//在指定位置显示一个字符,包括部分字符
//x:0~127
//y:0~63
//mode:0,反白显示;1,正常显示				 
//size:选择字体 16/8
void OLED_ShowChar(uint8_t x,uint8_t y, const uint8_t chr,uint8_t size)
{      	
	uint8_t i=0;	
	if(x>Max_Column-1){x=0;y=y+2;}
	if(size == SIZE_8X16)
	{
		OLED_SetPos(x,y);	
		for(i=0;i<8;i++)
			OLED_WR_Byte(F8X16[chr-' '][i],OLED_DATA);
		OLED_SetPos(x,y+1);
		for(i=0;i<8;i++)
			OLED_WR_Byte(F8X16[chr-' '][i+8],OLED_DATA);
	}
	if(size == SIZE_6X8)
	{	
		OLED_SetPos(x,y);
		for(i=0;i<6;i++)
			OLED_WR_Byte(F6X8[chr-' '][i],OLED_DATA);
	}
}
//m^n函数
uint32_t OLED_Pow(uint8_t m,uint8_t n)
{
	uint32_t result=1;	 
	while(n--)result*=m;    
	return result;
}				  
//显示2个数字
//x,y :起点坐标	 
//len :数字的位数
//size:字体大小
//mode:模式	0,填充模式;1,叠加模式
//num:数值(0~4294967295);	 		  
void OLED_ShowNum(uint8_t x,uint8_t y,uint32_t num,uint8_t len,uint8_t size)
{         	
	uint8_t t,temp;
	uint8_t enshow=0;						   
	for(t=0;t<len;t++)
	{
		temp=(num/OLED_Pow(10,len-t-1))%10;
		if(enshow==0&&t<(len-1))
		{
                  if(temp==0)
                  {
                          OLED_ShowChar(x+(size/2)*t,y,' ',size);
                          continue;
                  }else enshow=1;  	 
		}
	 	OLED_ShowChar(x+(size/2)*t,y,temp+'0',size); 
	}
} 
//显示一个字符号串
void OLED_ShowString(uint8_t x,uint8_t y,const uint8_t *str,uint8_t size)
{
	uint8_t j=0;
	while (str[j]!='\0')
	{	
		OLED_ShowChar(x,y,str[j],size);
		x+=8;
		if(x>120)	{x=0;y+=2;}
		j++;
	}
}
//显示汉字
void OLED_ShowChinese(uint8_t x, uint8_t y, uint8_t *chin, uint8_t size)
{      			    
    uint8_t i = 0;
    if(size == SIZE_GB16)
    {
      while (chin[i]!='\0')
      {	
          OLED_ShowGB16(x,y,chin+i);
          x+=16;
          if(x>120)	{x=0; y+=2;}
          i += 2;
      }
    }
    
    if(size == SIZE_GB24)
    {
      while (chin[i]!='\0')
      {	
          OLED_ShowGB24(x,y,chin+i);
          x+=24;
          if(x>120)	{x=0; y+=3;}
          i += 2;
      }
    }
}

void OLED_ShowGB16(uint8_t x, uint8_t y,uint8_t *chin)
{
  uint8_t i,j;

    for(i=0; i<GB_16_NUM; i++)
    {
      if((FGB16[i].Index[0]==*chin)&&(FGB16[i].Index[1]==*(chin+1)))
      {
        OLED_SetPos(x, y);
        for(j=0; j<16; j++)
        {
          OLED_WR_Byte(FGB16[i].Msk[j],OLED_DATA);
        }
        OLED_SetPos(x, y+1);
        for(j=0; j<16; j++)
        {	
          OLED_WR_Byte(FGB16[i].Msk[16+j],OLED_DATA);
        }	
        break;
      }	
    }
}

void OLED_ShowGB24(uint8_t x, uint8_t y,uint8_t *chin)
{
  uint8_t i,j;

    for(i=0; i<GB_24_NUM; i++)
    {
      if((FGB24[i].Index[0]==*chin)&&(FGB24[i].Index[1]==*(chin+1)))
      {
        OLED_SetPos(x, y);
        for(j=0; j<24; j++)
        {
          OLED_WR_Byte(FGB24[i].Msk[j],OLED_DATA);
        }
        OLED_SetPos(x, y+1);
        for(j=0; j<24; j++)
        {	
          OLED_WR_Byte(FGB24[i].Msk[24+j],OLED_DATA);
        }
        OLED_SetPos(x, y+2);
        for(j=0; j<24; j++)
        {	
          OLED_WR_Byte(FGB24[i].Msk[48+j],OLED_DATA);
        }	
        break;
      }	
    }
}

/***********功能描述：显示显示BMP图片128×64起始点坐标(x,y),x的范围0～127，y为页的范围0～7*****************/
void OLED_DrawBMP(uint8_t x0, uint8_t y0,uint8_t x1, uint8_t y1,uint8_t BMP[])
{ 	
  unsigned int j=0;
  uint8_t x,y;
 
  if(y1%8==0)          y = y1 / 8;      
  else                 y = y1/8 + 1;
  
  for(y=y0;y<y1;y++)
  {
    OLED_SetPos(x0,y);
    for(x=x0;x<x1;x++)
    {      
        OLED_WR_Byte(BMP[j++],OLED_DATA);	    	
    }
  }
} 


//初始化SSD1306					    
void OLED_Init(void)
{ 	
 	OLED_SIMIIC_Init();
	
	delay_ms(800);
	OLED_WR_Byte(0xAE,OLED_CMD);//--display off
	OLED_WR_Byte(0x00,OLED_CMD);//---set low column address
	OLED_WR_Byte(0x10,OLED_CMD);//---set high column address
	OLED_WR_Byte(0x40,OLED_CMD);//--set start line address  
	OLED_WR_Byte(0xB0,OLED_CMD);//--set page address
	OLED_WR_Byte(0x81,OLED_CMD); // contract control
	OLED_WR_Byte(0xFF,OLED_CMD);//--128   
	OLED_WR_Byte(0xA1,OLED_CMD);//set segment remap 
	OLED_WR_Byte(0xA6,OLED_CMD);//--normal / reverse
	OLED_WR_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)
	OLED_WR_Byte(0x3F,OLED_CMD);//--1/32 duty
	OLED_WR_Byte(0xC8,OLED_CMD);//Com scan direction
	OLED_WR_Byte(0xD3,OLED_CMD);//-set display offset
	OLED_WR_Byte(0x00,OLED_CMD);//
	
	OLED_WR_Byte(0xD5,OLED_CMD);//set osc division
	OLED_WR_Byte(0x80,OLED_CMD);//
	
	OLED_WR_Byte(0xD8,OLED_CMD);//set area color mode off
	OLED_WR_Byte(0x05,OLED_CMD);//
	
	OLED_WR_Byte(0xD9,OLED_CMD);//Set Pre-Charge Period
	OLED_WR_Byte(0xF1,OLED_CMD);//
	
	OLED_WR_Byte(0xDA,OLED_CMD);//set com pin configuartion
	OLED_WR_Byte(0x12,OLED_CMD);//
	
	OLED_WR_Byte(0xDB,OLED_CMD);//set Vcomh
	OLED_WR_Byte(0x30,OLED_CMD);//
	
	OLED_WR_Byte(0x8D,OLED_CMD);//set charge pump enable
	OLED_WR_Byte(0x14,OLED_CMD);//
	
	OLED_WR_Byte(0xAF,OLED_CMD);//--turn on oled panel
	
	OLED_Clear();
}  


